package org.tity.commons.concurrent;

import org.tity.commons.concurrent.pool.SimpleTaskManager;
import org.tity.commons.log.Logger;

/**
 * 超时任务
 * 指定任务以及执行超时的时长，如果任务超时未执行完毕，则自定取消任务
 * */
public class ResponsiveTask {
	
	
	private Runnable task;
	private long timeout;
	
	/**
	 * 线程池
	 * */
	
	private SimpleTaskManager taskMgr;
	private ThreadStopWay stopWay;
	/**
	 * 使用指定的线程池管理内部线程
	 * @param taskMgr 线程管理对象，线程池
	 * @param task	任务
	 * @param timeout	超时时长，毫秒
	 * @param stopWay	停止方式
	 * */
	public ResponsiveTask(SimpleTaskManager taskMgr,Runnable task,long timeout,ThreadStopWay stopWay)
	{
		this.taskMgr=taskMgr;
		this.task=task;
		this.timeout=timeout;
		this.stopWay=stopWay;
	}
	
	/**
	 * @return 任务完成后的回调
	 * */
	public Runnable getCompleteCallback() {
		return completeCallback;
	}

	/**
	 * 设置任务完成后的回调
	 * @param completeCallback 任务完成后的回调
	 * */
	public void setCompleteCallback(Runnable completeCallback) {
		this.completeCallback = completeCallback;
	}

	/**
	 * @return 任务执行超时的回调
	 * */
	public Runnable getTimeoutCallback() {
		return timeoutCallback;
	}

	/**
	 * 设置任务执行超时的回调
	 * @param timeoutCallback 任务执行超时的回调
	 * */
	public void setTimeoutCallback(Runnable timeoutCallback) {
		this.timeoutCallback = timeoutCallback;
	}

	/**
	 * @return 任务取消时的回调
	 * */
	public Runnable getCancelCallback() {
		return cancelCallback;
	}

	/**
	 * 设置任务取消时的回调
	 * @param cancelCallback 任务取消时的回调
	 * */
	public void setCancelCallback(Runnable cancelCallback) {
		this.cancelCallback = cancelCallback;
	}

	/**
	 * @return 任务超时时间
	 * */
	public long getTimeout() {
		return timeout;
	}

	private Runnable completeCallback  = null;
	private Runnable timeoutCallback  = null;
	private Runnable cancelCallback  = null;
	
	/**
	 * 使用独立的线程池管理内部线程
	 * @param task	任务
	 * @param timeout	超时时长，毫秒
	 * @param stopWay	停止方式
	 * */
	public ResponsiveTask(Runnable task,long timeout,ThreadStopWay stopWay)
	{
		 this(new SimpleTaskManager(2),task,timeout,stopWay);
	}
	
	private static class Task implements Runnable
	{
		private ResponsiveTask responsiveTask;
		public Task(ResponsiveTask responsiveTask)
		{
			super();
			this.responsiveTask=responsiveTask;
		}
		@Override
		public void run() {
			try {
				responsiveTask.timecost=System.currentTimeMillis();
				responsiveTask.task.run();
				responsiveTask.timecost=System.currentTimeMillis()-responsiveTask.timecost;
				responsiveTask.onTaskComplete();
			} catch (Exception e) {
				responsiveTask.timecost=-1L;
				Logger.exception(e);
			}
		}
	}
	
	private static class TimeoutTask implements Runnable
	{
		private ResponsiveTask responsiveTask;
		
		public TimeoutTask(ResponsiveTask responsiveTask)
		{
			super();
			this.responsiveTask=responsiveTask;
		}
		@Override
		public void run() {
			this.responsiveTask.onTaskTimeout();
		}
	}
	
	private int taskId;
	private int timoutTaskId;
	private volatile  Thread mainThread=null;
	
	private long timecost=-1L;
	
	public void start()
	{
	 
		timoutTaskId=taskMgr.doDelayTask(new TimeoutTask(this), this.timeout);
		taskId=taskMgr.doDelayTask(new Task(this), 2);
//		Logger.info("task started");
		
		mainThread=Thread.currentThread();
		
		//使主调线程等待
		synchronized (mainThread) {
			try {
				mainThread.wait();
			} catch (Exception e) {
				Logger.exception(e);
			}
		}
	}
	
	private void backToMainThread()
	{
		synchronized (mainThread) {
			try {
				mainThread.notify();
			} catch (Exception e) {
				Logger.exception(e);
			}
		}
	}

	private void onTaskComplete()
	{
		//清除超时任务
		taskMgr.clearTask(timoutTaskId);
//		Logger.info("task completed , timecost : "+timecost+" ms");
		//唤醒主调线程
		backToMainThread();
		//回调
		if(completeCallback!=null) {
			completeCallback.run();
		}
	}
	
	public void onTaskTimeout() {
		Logger.info("task timeout");
		//清除的任务
		this.taskMgr.clearTask(this.taskId,true,stopWay);
		//唤醒主调线程
		backToMainThread();
		//回调
		if(timeoutCallback!=null) {
			timeoutCallback.run();
		}
	}
	
	
	public void cancel()
	{
		//清除的任务
		this.taskMgr.clearTask(this.taskId,true,stopWay);
		//清除超时任务
		taskMgr.clearTask(this.timoutTaskId,true);
		//唤醒主调线程
		backToMainThread();
		//回调
		if(cancelCallback!=null) {
			cancelCallback.run();
		}
	}
	
	
 
}
